﻿using System;

namespace Jasmine.Extensions.Strings
{
    public static class StringExtension
    {
        /// <summary>
        /// Indicates whether the specified string is null or an System.String.Empty string.
        /// </summary>
        /// <param name="value">The string to test.</param>
        /// <returns>ttrue if the value parameter is null or an empty string (""); otherwise, false.</returns>
        public static bool IsNullOrEmpty(this string value) => string.IsNullOrEmpty(value.Trim());

        /// <summary>
        /// Indicates whether a specified string is null, empty, or consists only of white-space characters.
        /// </summary>
        /// <param name="value">The string to test.</param>
        /// <returns>true if the value parameter is null or System.String.Empty, or if value consists exclusively of white-space characters.</returns>
        public static bool IsNullOrWhiteSpace(this string value) => string.IsNullOrWhiteSpace(value.Trim());

        /// <summary>
        /// Converts the specified string representation of a date and time to its equivalent <see cref="DateTime"/>
        /// value using the provided format or a set of default formats.
        /// </summary>
        /// <remarks>If the <paramref name="format"/> parameter is null, empty, or consists only of
        /// white-space characters, the method attempts to parse the input using several common date and time formats.
        /// If parsing is unsuccessful, the method returns <see cref="DateTime.UtcNow"/> instead of throwing an
        /// exception. This method always adjusts the result to universal time.</remarks>
        /// <param name="value">The string containing a date and time to convert.</param>
        /// <param name="format">An optional format string that defines the expected date and time format. If not specified or empty, several
        /// standard formats are attempted.</param>
        /// <returns>A <see cref="DateTime"/> value that represents the parsed date and time. If parsing fails, returns the
        /// current UTC date and time.</returns>
        public static DateTime ToDateTime(this string value, string format = "")
        {
            if (format.IsNullOrWhiteSpace())
            {
                return DateTime.TryParseExact(value, new string[] { "yyyy-MM-ddTHH:mm:ss.fffZ", "yyyy-MM-ddTHH:mm:ssZ", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd", "yyyyMMdd" }, null, System.Globalization.DateTimeStyles.AdjustToUniversal, out DateTime result) ? result : DateTime.UtcNow;
            }
            else
            {
                return DateTime.TryParseExact(value, format, null, System.Globalization.DateTimeStyles.AdjustToUniversal, out DateTime result) ? result : DateTime.UtcNow;
            }
        }

        /// <summary>
        /// Converts the specified string representation of a date and time to a DateTimeOffset value.
        /// </summary>
        /// <remarks>If the input string cannot be parsed as a valid date and time, this method returns
        /// DateTimeOffset.UtcNow instead of throwing an exception. This behavior may result in unexpected values if the
        /// input is invalid; callers should validate input as needed.</remarks>
        /// <param name="value">The string containing a date and time to convert. If the string is not a valid date and time format, the
        /// current UTC date and time is returned.</param>
        /// <returns>A DateTimeOffset value parsed from the input string, or the current UTC date and time if parsing fails.</returns>
        public static DateTimeOffset ToDateTimeOffset(this string value) => DateTimeOffset.TryParse(value, out DateTimeOffset result) ? result : DateTimeOffset.UtcNow;

        /// <summary>
        /// Converts the specified string to a <see cref="Guid"/> value. Returns <see cref="Guid.Empty"/> if the string
        /// is not a valid GUID representation.
        /// </summary>
        /// <remarks>This method does not throw an exception if the input string is not a valid GUID. If
        /// the conversion is unsuccessful, <see cref="Guid.Empty"/> is returned.</remarks>
        /// <param name="value">The string to convert to a <see cref="Guid"/>. Can be in any format recognized by <see
        /// cref="Guid.TryParse(string, out Guid)"/>.</param>
        /// <returns>A <see cref="Guid"/> parsed from the input string, or <see cref="Guid.Empty"/> if the conversion fails.</returns>
        public static Guid ToGuid(this string value) => Guid.TryParse(value, out Guid result) ? result : Guid.Empty;

        /// <summary>
        /// Converts the specified string representation of a logical value to its Boolean equivalent.
        /// </summary>
        /// <remarks>If the input string is null, empty, or does not match a valid Boolean value, the
        /// method returns false. This method is useful for safely parsing user input or configuration values to Boolean
        /// without throwing exceptions.</remarks>
        /// <param name="value">The string to convert to a Boolean value. Accepts "True" or "False" (case-insensitive).</param>
        /// <returns>true if the string represents a Boolean true value; otherwise, false.</returns>
        public static bool ToBool(this string value) => bool.TryParse(value, out bool result) && result;

        /// <summary>
        /// Converts the specified string representation of a number to its 32-bit signed integer equivalent.
        /// </summary>
        /// <remarks>If the input string is null, empty, or not a valid integer, the method returns 0
        /// without throwing an exception. This method is useful for safely converting user input or external data to an
        /// integer.</remarks>
        /// <param name="value">The string containing the number to convert. If the string is not a valid integer, the method returns 0.</param>
        /// <returns>The 32-bit signed integer value equivalent to the input string, or 0 if the conversion fails.</returns>
        public static int ToInt(this string value) => int.TryParse(value, out int result) ? result : 0;

        /// <summary>
        /// Converts the specified string representation of a number to its 64-bit signed integer equivalent. Returns 0
        /// if the conversion fails.
        /// </summary>
        /// <remarks>This method does not throw an exception if the conversion fails. If <paramref
        /// name="value"/> is null, empty, or not a valid long integer, the method returns 0.</remarks>
        /// <param name="value">The string containing the number to convert.</param>
        /// <returns>A 64-bit signed integer equivalent to the numeric value contained in <paramref name="value"/>; or 0 if
        /// <paramref name="value"/> is not a valid representation of a long integer.</returns>
        public static long ToLong(this string value) => long.TryParse(value, out long result) ? result : 0L;

        /// <summary>
        /// Converts the specified string representation of a number to its decimal equivalent. Returns zero if the
        /// conversion fails.
        /// </summary>
        /// <remarks>If the input string is not a valid decimal number, the method returns zero instead of
        /// throwing an exception. This method is useful for safely parsing user input or external data where the format
        /// may not be guaranteed.</remarks>
        /// <param name="value">The string containing a number to convert to a decimal.</param>
        /// <returns>The decimal value equivalent to the input string, or zero if the string cannot be converted.</returns>
        public static decimal ToDecimal(this string value) => decimal.TryParse(value, out decimal result) ? result : 0M;
        /// <summary>
        /// Converts the specified string representation of a number to its double-precision floating-point equivalent.
        /// </summary>
        /// <remarks>This method does not throw an exception if the conversion fails. If <paramref
        /// name="value"/> is null, empty, or not a valid double, the method returns 0.0.</remarks>
        /// <param name="value">The string containing the number to convert. If the string is not a valid double, the method returns 0.0.</param>
        /// <returns>A double-precision floating-point number equivalent to the numeric value contained in <paramref
        /// name="value"/>; or 0.0 if the conversion fails.</returns>
        public static double ToDouble(this string value) => double.TryParse(value, out double result) ? result : 0.0;
        /// <summary>
        /// Converts the specified string representation of a number to its single-precision floating-point equivalent.
        /// </summary>
        /// <remarks>This method does not throw an exception if the conversion fails; instead, it returns
        /// 0. Use this method when you want a safe conversion without error handling for invalid input.</remarks>
        /// <param name="value">The string containing the number to convert. If the string is not a valid representation of a floating-point
        /// number, the method returns 0.</param>
        /// <returns>The single-precision floating-point number equivalent to the input string, or 0 if the conversion fails.</returns>
        public static float ToFloat(this string value) => float.TryParse(value, out float result) ? result : 0f;

    }
}
